require('Extend');

function BaseHttpLink(url, param) {
    this.request = function (OKcbk, NOcbk) {
        var success = (data) => {
            OKcbk && OKcbk(data);
        }
        var failure = (error, code) => {
            NOcbk && NOcbk(error, code);
        }
        var xhr = new XMLHttpRequest();
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.setRequestHeader('Authorization', LINK.accessToken);
        xhr.setRequestHeader('App-Channel', LINK.appChannel);
        xhr.setRequestHeader('App-Version', CONFIG.appVersion);
        xhr.setRequestHeader('Accept-Language', CONFIG.language);
        xhr.setRequestHeader('Repeated-Submission', (new Date()).getTime().toString());
        xhr.timeout = 10000;
        xhr.ontimeout = function () {
            failure(LangPublic.W001);
        };
        xhr.onerror = function () {
            failure(LangPublic.W002);
        };
        xhr.onreadystatechange = () => {
            if (xhr.readyState !== 4) return;
            if (xhr.status >= 200 && xhr.status <= 207) {
                if (xhr.responseText) {
                    var result = JSON.parse(xhr.responseText);
                    if (result.code === 200) {
                        success(result.data);
                    } else if (result.code === 401) {
                        failure(LangPublic.W003, result.code);
                    }else {
                        failure(result.message, result.code);
                    }
                }
            } else {
                failure(LangPublic.W004, xhr.status);
            }
        };

        param ? xhr.send(JSON.stringify(param)) : xhr.send();
        cc.Proxy.appLog(url);
        return this;
    }
}

function CacheHttpLink(url) {
    var result = null;
    var callbacks = [];
    this.request = function(OKcbk, NOcbk, target) {
        for(var i in callbacks) {
            var d = callbacks[i];
            if(d.target == target && d.OKcbk == OKcbk) return this;
        }
        callbacks.push({
            target: target,
            OKcbk: OKcbk,
            NOcbk: NOcbk
        })
        return this;
    }
    this.refresh = function() {
        new BaseHttpLink(url).request(data => {
            result = data;
            for(var i in callbacks) {
                var d = callbacks[i];
                d.OKcbk && d.OKcbk.call(d.target, data);
            }
        }, (error, code) => {
            for(var i in callbacks) {
                var d = callbacks[i];
                d.NOcbk && d.NOcbk.call(d.target, error, code);
            }
        });
        return this;
    }
}

var CacheLinks = (function() {
    var linksMap = {};
    var urlName = function(url) {
        for(var i in URL) if(URL[i] == url) return i;
        return 'null';
    }
    return {
        syncData() {
            for(var i in linksMap) linksMap[i].refresh();
        },
        addLink(url, link) {
            linksMap[urlName(url)] = link;
        },
        getLink(url) {
            return linksMap[urlName(url)];
        }
    }
})();

function MultiHttpLink(url, param) {
    var isAutoLogin = false;
    var isShowLoading = true;
    var isShowMessage = true;
    var cacheLink = CacheLinks.getLink(url);
    this.autoLogin = function (value) {
        isAutoLogin = value;
        return this;
    }
    this.showLoading = function (value) {
        isShowLoading = value;
        return this;
    }
    this.showMessage = function (value) {
        isShowMessage = value;
        return this;
    }
    this.refresh = function() {
        cacheLink && cacheLink.refresh();
        return this;
    }
    this.request = function(OKcbk, NOcbk, target) {
        if (!url) return this;
        if(NOcbk && typeof(NOcbk) == 'object') {
            target = NOcbk;
            NOcbk = null;
        }
        if(target && !param) {
            if(!cacheLink) {
                cacheLink = new CacheHttpLink(url);
                CacheLinks.addLink(url, cacheLink);
            }
            cacheLink.request(OKcbk, NOcbk, target);
        } else {
            isShowLoading && cc.Toast.loading(true);
            var success = (data) => {
                isShowLoading && cc.Toast.loading(false);
                OKcbk && OKcbk(data);
            }
            var failure = (error, code) => {
                isShowLoading && cc.Toast.loading(false);
                if (isShowMessage) cc.Toast.message(error);
                if (isAutoLogin && code === 401) cc.Proxy.callLogin();
                NOcbk && NOcbk(error, code);
            }
            new BaseHttpLink(url, param).request(success, failure);
        }
        return this;
    }
}

cc.Linker = function (url, param) {
    return new MultiHttpLink(url, param);
}

cc.Emitter.on(EVENTS.USER_LOGOUT, CacheLinks.syncData, CacheLinks);
cc.Emitter.on(EVENTS.REFRESH_STATE, CacheLinks.syncData, CacheLinks);
